package com.yanfan.energy.service.impl;

import cn.hutool.core.util.StrUtil;
import com.yanfan.attach.mapper.DeviceDetailMapper;
import com.yanfan.common.core.domain.entity.SysUser;
import com.yanfan.common.utils.SecurityUtils;
import com.yanfan.energy.domain.Building;
import com.yanfan.energy.domain.Workshop;
import com.yanfan.energy.domain.statist.*;
import com.yanfan.energy.mapper.*;
import com.yanfan.energy.service.EnergyBoardService;
import com.yanfan.energy.util.WidgetUtil;
import com.yanfan.iot.domain.Device;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author caijinkang
 * @date 2022年09月30日 9:25
 */
@Service("energyBoardServiceImpl")
@Transactional(rollbackFor = Exception.class)
public class EnergyBoardServiceImpl implements EnergyBoardService {

    public static final String Day = "day";
    public static final String WEEK = "week";
    public static final String MONTH = "month";
    public static final String HOUR = "hour";
    private static final ZoneId zone = ZoneId.systemDefault();
    @Resource
    private OverallEnergyDao overallEnergyDao;
    @Resource
    private WorkshopDao workshopDao;
    @Resource
    private EnergyPriceSettingDao energyPriceSettingDao;
    @Resource
    private BuildingDao buildingDao;
    @Resource
    private DeviceDetailMapper deviceDetailMapper;
    @Resource
    private DeviceEnergyMapper deviceEnergyMapper;
    @Autowired
    private PurchasingEnergysDao purchasingEnergyDao;

    @Override
    public Map<String, List<DateStatistics>> findTotalBoard(String range, LocalDate begin, LocalDate end, Integer unit) {

        String format = "%Y-%m-%d";
        String datetime = "'%Y-%m-%d'";
        List<String> dates = new ArrayList();

        if (StrUtil.isEmpty(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            end = end.plusDays(1);
            for (LocalDate date = begin; date.isBefore(end); date = date.plusDays(1)) {
                dates.add(formatter.format(date));
            }
        }

        if (Day.equals(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            begin = begin.plusDays(-begin.getDayOfMonth() + 1);
            end = end.plusDays(-end.getDayOfMonth() + 1);
            end = end.plusMonths(1);
            for (LocalDate date = begin; date.isBefore(end); date = date.plusDays(1)) {
                dates.add(formatter.format(date));
            }
        } else if (WEEK.equals(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            begin = begin.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
            end = end.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
            end = end.plusDays(1);
            for (LocalDate date = begin; date.isBefore(end); date = date.plusDays(1)) {
                dates.add(formatter.format(date));
            }
        } else if (MONTH.equals(range)) {
            begin = begin.plusDays(-begin.getDayOfYear() + 1);
            end = begin.plusMonths(11);
            format = "%Y-%m";
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM").withZone(zone);
            end = end.plusMonths(1);
            for (LocalDate date = begin; date.isBefore(end); date = date.plusMonths(1)) {
                dates.add(formatter.format(date));
            }
            datetime = "'%Y-%m'";
        }

        Map<String, List<DateStatistics>> resultCount = new LinkedHashMap<>();

        List<Building> buildings = buildingDao.findAllBuilding();

        final String date = datetime;
        final LocalDate beginOn = begin;
        final LocalDate endOn = end;

        buildings.stream().forEach(bu -> {

            Map<String, Map<String, List<DateStatistics>>> list = new LinkedHashMap<>();

            List<DateStatistics> statistics = workshopDao.findAllEnergyByBuildingId(date, bu
                    .getBuildId()
                    .longValue(), beginOn, endOn);

            List<DateStatistics> BuildingData = new ArrayList<>();
            List<DateStatistics> BuildingList = new ArrayList<>();

            statistics.stream().forEach(s -> {
                BuildingData.add(s);
            });

            BuildingData
                    .parallelStream()
                    .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                    .forEach((id, transfer) -> {
                        transfer
                                .stream()
                                .reduce((a, b) -> new DateStatistics(a.getNumber().longValue() + b
                                        .getNumber()
                                        .longValue(), a.getDate(), a.getNumber() + b.getNumber()))
                                .ifPresent(BuildingList::add);
                    });

            List<DateStatistics> statisticsList = findDateStatistics(dates, BuildingList);
            statisticsList.stream().forEach(s -> {
                s.setNumber(s.getCount().doubleValue());
            });

            resultCount.put(bu.getBuildName(), statisticsList);
        });

        return resultCount;
    }

    @Override
    public Map<String, List<DateStatistics>> findWorkshopEnergyNo(String range, LocalDate begin, LocalDate end, Integer unit) {
        return null;
    }

    @Override
    public Map<String, List<DateStatistics>> findMediumEnergyNo(String range, LocalDate begin, LocalDate end, Integer unit) {
        return null;
    }

    @Override
    public Map<String, List<DateStatistics>> findTotalCrest(String range, LocalDate begin, LocalDate end, Integer unit) {

        String format = "%Y-%m-%d";
        String datetime = "'%Y-%m-%d'";
        List<String> dates = new ArrayList();

        if (StrUtil.isEmpty(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            end = end.plusDays(1);
        }

        if (Day.equals(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            begin = LocalDate.now();
            end = begin.plusDays(1);
        } else if (WEEK.equals(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            begin = begin.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
            end = end.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
            end = end.plusDays(1);

        } else if (MONTH.equals(range)) {
            format = "%Y-%m";
            begin = begin.plusDays(-begin.getDayOfMonth() + 1);
            end = begin.plusMonths(1);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM").withZone(zone);

            datetime = "'%Y-%m'";
        }

        List<DateStatistics> spikes = new ArrayList<>();
        List<DateStatistics> peaks = new ArrayList<>();
        List<DateStatistics> parity = new ArrayList<>();
        List<DateStatistics> lowEbb = new ArrayList<>();

        List<DateStatistics> electric = new ArrayList<>();
        if (unit == 1) {
            electric = workshopDao.findAllEnergyByNo(datetime, null, begin, end);
        } else if (unit == 0) {
            electric = workshopDao.findAllEnergyByNoMo(datetime, null, begin, end);
        }

        Map<String, List<DateStatistics>> result = new LinkedHashMap<>();

        electric.stream().forEach(e -> {
            if (e.getCount() == 7) {
                e.setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                spikes.add(e);
            }
            if (e.getCount() == 8) {
                e.setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                peaks.add(e);
            }
            if (e.getCount() == 9) {
                e.setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                parity.add(e);
            }
            if (e.getCount() == 10) {
                e.setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                lowEbb.add(e);
            }

        });

        List<DateStatistics> spikesList = new ArrayList<>();
        List<DateStatistics> peaksList = new ArrayList<>();
        List<DateStatistics> parityList = new ArrayList<>();
        List<DateStatistics> lowEbbList = new ArrayList<>();

        spikes
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(spikesList::add);
                });
        peaks
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(peaksList::add);
                });
        parity
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(parityList::add);
                });
        lowEbb
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(lowEbbList::add);
                });

        result.put("spikes", spikesList);
        result.put("peaks", peaksList);
        result.put("parity", parityList);
        result.put("lowEbb", lowEbbList);

        List<DateStatistics> workshopData = new ArrayList<>();
        List<DateStatistics> workshopList = new ArrayList<>();

        result.forEach((key, value) -> {
            value.forEach(s -> {
                workshopData.add(s);
            });
        });

        workshopData
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(workshopList::add);
                });

        result.forEach((k, v) -> {
            workshopList.stream().forEach(w -> {
                v.stream().forEach(s -> {
                    s.setCount(s.getNumber().longValue());
                    BigDecimal number = new BigDecimal(s.getNumber() / w.getNumber() * 100);
                    double count = number.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                    s.setNumber(count);
                });
            });
            if (v.isEmpty()) {
                v.add(new DateStatistics(0L, LocalDateTime
                        .now()
                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), 0.00));
            }
        });

        return result;
    }

    @Override
    public List<EnvironmentStatics> findTemperature() {
        return workshopDao.findTemperature();
    }

    @Override
    public List<EnvironmentStatics> findElectricity() {
        return workshopDao.findElectricity();
    }

    @Override
    public Map<String, List<DateStatistics>> findCountElectricity(String range, LocalDate begin, LocalDate end) {

        RangeStatistics rangeStatistics = findDateByRange(range, begin, end, "%Y-%m-%d", "'%Y-%m-%d'");

        List<DayEnergyStatistics> dayEnergyStatistics = workshopDao.findUnitOfElectricity(rangeStatistics.getDatetime(), null, rangeStatistics.getBegin(), rangeStatistics.getEnd());

        List<DateStatistics> electricity = dayEnergyStatistics
                .stream()
                .map(d -> new DateStatistics(d.getElectricity().longValue(), d.getDate(), 0.00))
                .collect(Collectors.toList());

        Map<String, List<DateStatistics>> result = new LinkedHashMap<>();

        result.put("energy", findDateStatistics(rangeStatistics.getDates(), electricity));
        return result;
    }

    @Override
    public List<Building> findFloorInformation() {
        return buildingDao.findFloorInformation();
    }

    @Override
    public List<DateStatistics> findPriceStatistics(List<DateStatistics> dateStatistics, Integer unit, Integer type) {

        dateStatistics.stream().forEach(o -> {
            if (energyPriceSettingDao.selectAllEnergyPriceSettingByCount(type) != 0) {
                double price = 0.00;
                price = energyPriceSettingDao.selectAllEnergyPriceSettingByType(type);
                if (o.getCount().intValue() != 0 && price != 0.00) {
                    if (unit == 0) {
                        o.setNumber(new BigDecimal(price * o.getCount())
                                            .setScale(2, BigDecimal.ROUND_HALF_UP)
                                            .doubleValue());
                    }
                    if (unit == 1) {
                        o.setNumber(new BigDecimal(price * o.getCount() / 10000)
                                            .setScale(2, BigDecimal.ROUND_HALF_UP)
                                            .doubleValue());
                    }
                }
            }
        });

        return dateStatistics;
    }

    @Override
    public Map<String, List<DateStatistics>> findWorkshopEnergy(Map<String, List<DateStatistics>> d) {

        List<DateStatistics> workshopData = new ArrayList<>();
        List<DateStatistics> workshopList = new ArrayList<>();

        d.forEach((key, value) -> {
            value.forEach(s -> {
                workshopData.add(s);
            });
        });

        workshopData
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(workshopList::add);
                });

        Map<String, List<DateStatistics>> result = new LinkedHashMap<>();
        result.put("workshopData", workshopList);

        return result;
    }

    @Override
    public List<DateStatistics> findDateStatistics(List<String> dates, List<DateStatistics> statistics) {
        Map<String, Long> map = statistics
                .stream()
                .collect(Collectors.toMap(DateStatistics::getDate, DateStatistics::getCount));
        return dates
                .stream()
                .map(d -> new DateStatistics(map.getOrDefault(d, 0L), d, 0.00))
                .collect(Collectors.toList());
    }

    @Override
    public Map<String, List<DateStatistics>> findMediaDistribute(String range, LocalDate begin, LocalDate end, Integer unit) {

        String format = "%Y-%m-%d";
        String datetime = "'%Y-%m-%d'";
        List<String> dates = new ArrayList();

        if (StrUtil.isEmpty(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            end = end.plusDays(1);
        }

        if (Day.equals(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            begin = LocalDate.now();
            end = begin.plusDays(1);
        } else if (WEEK.equals(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            begin = begin.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
            end = end.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
            end = end.plusDays(1);

        } else if (MONTH.equals(range)) {
            format = "%Y-%m";
            begin = begin.plusDays(-begin.getDayOfMonth() + 1);
            end = begin.plusMonths(1);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM").withZone(zone);

            datetime = "'%Y-%m'";
        }

        Map<String, List<DateStatistics>> countRes = findAllEnergy(findEnergyByType(datetime, null, begin, end, 1));

        List<DateStatistics> workshopData = new ArrayList<>();
        List<DateStatistics> workshopList = new ArrayList<>();

        countRes.forEach((k, v) -> {
            v.forEach(s -> {
                s.setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                workshopData.add(s);
            });
        });

        workshopData
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(workshopList::add);
                });

        countRes.forEach((k, v) -> {
            v.forEach(cr -> {
                workshopList.stream().forEach(w -> {
                    cr.setCount(cr.getNumber().longValue());
                    BigDecimal number = new BigDecimal(cr.getNumber() / new BigDecimal(w.getNumber())
                            .setScale(2, BigDecimal.ROUND_HALF_UP)
                            .doubleValue() * 100);
                    double count = number.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
                    cr.setNumber(count);
                });
            });
            if (v.isEmpty()) {
                v.add(new DateStatistics(0L, LocalDateTime
                        .now()
                        .format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), 0.00));
            }
        });

        return countRes;
    }

    @Override
    public Map<String, List<DateStatistics>> findAllEnergy(Map<String, List<DateStatistics>> stringListMap) {

        List<DateStatistics> waterData = new ArrayList<>();
        List<DateStatistics> compressedAirData = new ArrayList<>();
        List<DateStatistics> electricData = new ArrayList<>();

        stringListMap.forEach((key, value) -> {

            value.stream().forEach(v -> {
                if (v.getCount() == 1 || v.getCount() == 2 || v.getCount() == 3) {
                    v.setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    waterData.add(v);
                }
                if (v.getCount() == 4 || v.getCount() == 5 || v.getCount() == 6) {
                    v.setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    compressedAirData.add(v);
                }
                if (v.getCount() == 7 || v.getCount() == 8 || v.getCount() == 9 || v.getCount() == 10) {
                    v.setDate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                    electricData.add(v);
                }
            });

        });

        List<DateStatistics> waterList = new ArrayList<>();
        List<DateStatistics> compressedAirList = new ArrayList<>();
        List<DateStatistics> electricList = new ArrayList<>();

        waterData
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(waterList::add);
                });


        compressedAirData
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(compressedAirList::add);
                });
        electricData
                .parallelStream()
                .collect(Collectors.groupingBy(o -> (o.getDate()), Collectors.toList()))
                .forEach((id, transfer) -> {
                    transfer
                            .stream()
                            .reduce((a, b) -> new DateStatistics(a.getCount(), a.getDate(), a.getNumber() + b.getNumber()))
                            .ifPresent(electricList::add);
                });


        Map<String, List<DateStatistics>> result = new LinkedHashMap<>();
        result.put("waterData", waterList);
        result.put("compressedAirData", compressedAirList);
        result.put("electricList", electricList);

        return result;
    }

    @Override
    public Map<String, List<DateStatistics>> findEnergyByType(String datetime, Long workshopId, LocalDate begin, LocalDate end, Integer byType) {

        Map<String, List<DateStatistics>> result = new LinkedHashMap<>();

        // 查询1-11的能耗类型数据，并计算好价格
        if (byType == 1) {
            List<DateStatistics> allEnergy = workshopDao.findAllEnergyByNo(datetime, workshopId, begin, end);
            result.put("energy", allEnergy);
        }

        return result;
    }

    @Override
    public List<Building> findAllBuilding() {
        SysUser user = SecurityUtils.getLoginUser().getUser();

        // 管理员查看所有
        if (user.isAdmin()) {
            return buildingDao.findAllBuilding();
        }
        List<Building> buildings1 = buildingDao.findAllBuildingByDeptId(SecurityUtils.getDeptId().intValue());
        return buildings1;
    }

    @Override
    public List<DateStatistics> findAllWorkshopByBuildId(Integer buildId) {
        return workshopDao.findAllWorkShopByBuildId(buildId);
    }

    @Override
    public List<Device> findAllDeviceByWorkshop(List<Workshop> workshops) {
        List<Device> iotDeviceList = new ArrayList<>();
        //判空
        if (workshops.isEmpty()) {
            workshops.add(new Workshop());
        }
        workshops.stream().forEach(w -> {
            List<Device> workshopList = new ArrayList<>();
            if (SecurityUtils.getUserId() == 256) {
                workshopList = deviceDetailMapper.findAllDeviceByWorkshopId(w.getId(), 20);
            } else {
                workshopList = deviceDetailMapper.findAllDeviceByWorkshopId(w.getId(), null);
            }
            workshopList.stream().forEach(ws -> {
                iotDeviceList.add(ws);
            });
        });

        return iotDeviceList;
    }

    @Override
    public DayEnergyStatistics findEnergyByToday(Long workshopId, Integer unit) {

        DayEnergyStatistics result = new DayEnergyStatistics();
        if (unit == 0) {
            result = workshopDao.findEnergyByToday(workshopId);
        }
        if (unit == 1) {
            result = workshopDao.findEnergyByTodayAndPrice(workshopId);
        }
        return result;
    }

    @Override
    public UnitOfStatistics findUnitOfElectricity(Integer workshopId, String range, LocalDate begin, LocalDate end, Integer unit) {

        RangeStatistics rangeStatistics = findDateByRange(range, begin, end, "%Y-%m-%d", "'%Y-%m-%d'");

        // 用电
        List<DateByStatistics> electricity = new ArrayList<>();
        // 所有能耗
        List<DateStatistics> allEnergy = overallEnergyDao.findConsumeWaterByUnit(rangeStatistics.getDatetime(), workshopId, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd());
        // 4：压缩空气
        List<DateStatistics> compress = allEnergy.stream().filter(d -> d.getCount() == 4L).collect(Collectors.toList());
        // 1：冷却水(空调热能)
        List<DateStatistics> air = allEnergy.stream().filter(d -> d.getCount() == 1L).collect(Collectors.toList());
        // 2：软化水(自来水)
        List<DateStatistics> softening = allEnergy
                .stream()
                .filter(d -> d.getCount() == 2L)
                .collect(Collectors.toList());
        // 默认单位：能耗
        if (unit == 0) {
            // 用电
            List<DateByStatistics> daoTotalCost = deviceEnergyMapper.findConsumeElectricity(rangeStatistics.getDatetime(), workshopId, null, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd());
            electricity = WidgetUtil.mergeByDateBy(daoTotalCost);

        }
        // 能耗价格：万元
        if (unit == 1) {
            // 用电
            List<DateByStatistics> daoTotalCost = deviceEnergyMapper.findConsumeElectricityPrice(rangeStatistics.getDatetime(), workshopId, null, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd());
            // 查询所有单价(查找8为峰电、9为平电、10为谷电的单价)
            electricity = WidgetUtil.mergeByDateBy(daoTotalCost);

            // 4：压缩空气
            // 总压缩空气设备电费/总压缩空气(流量计m3)=压缩空气单价x压缩空气能耗m3=压缩空气费用
            List<DateByStatistics> daoTotalByCompress = daoTotalCost
                    .stream()
                    .filter(d -> d.getHour().equals("4"))
                    .collect(Collectors.toList());
            // 得到压缩空气总用电
            List<DateStatistics> compressByElectricity = WidgetUtil.mergeByElectricityPrice(daoTotalByCompress);
            // 得到压缩空气总能耗
            List<DateStatistics> cooling = WidgetUtil.mergeByEnergyPrice(compress);
            compress.stream().forEach(d -> {
                if (compressByElectricity.isEmpty()) {
                    compressByElectricity.add(new DateStatistics(0L, "", 0.00));
                }
                if (cooling.isEmpty() || cooling.get(0).getNumber() == 0.00) {
                    cooling.add(new DateStatistics(0L, "", 1.00));
                    cooling.get(0).setNumber(1.00);
                }

                Double unitPrice = compressByElectricity.stream().findFirst().get().getNumber() / cooling
                        .stream()
                        .findFirst()
                        .get()
                        .getNumber();
                d.setNumber(new BigDecimal(d.getNumber() * unitPrice / 10000)
                                    .setScale(4, BigDecimal.ROUND_HALF_UP)
                                    .doubleValue());
            });

            // 热能(冷却水)
            // 电费 -> 1：设备类型为空调热能(冷却水)的
            List<DateByStatistics> daoTotalByCooling = daoTotalCost
                    .stream()
                    .filter(d -> d.getHour().equals("1"))
                    .collect(Collectors.toList());
            // 得到冷却水总用电
            List<DateStatistics> coolingByElectricity = WidgetUtil.mergeByElectricityPrice(daoTotalByCooling);
            // 得到冷却水总能耗
            List<DateStatistics> coolingCount = WidgetUtil.mergeByEnergyPrice(air);
            air.stream().forEach(d -> {
                if (coolingByElectricity.isEmpty()) {
                    coolingByElectricity.add(new DateStatistics(0L, "", 0.00));
                }
                if (coolingCount.isEmpty() || coolingCount.get(0).getNumber() == 0.00) {
                    coolingCount.add(new DateStatistics(0L, "", 1.00));
                    coolingCount.get(0).setNumber(1.00);
                }
                Double unitPrice = coolingByElectricity.stream().findFirst().get().getNumber() / coolingCount
                        .stream()
                        .findFirst()
                        .get()
                        .getNumber();
                d.setNumber(new BigDecimal(d.getNumber() * unitPrice / 10000)
                                    .setScale(4, BigDecimal.ROUND_HALF_UP)
                                    .doubleValue());
            });

            // 自来水(软化水) * 单价
            softening = overallEnergyDao.findConsumeWater(rangeStatistics.getDatetime(), workshopId, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd());
            // 电能(万元)
            electricity.stream().forEach(e -> {
                e.setNumber(new BigDecimal(e.getNumber() / 10000).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
            });
        }

        // 电能
        List<DateStatistics> el = WidgetUtil.mergeElementByOld(electricity
                                                                       .stream()
                                                                       .map(d -> new DateStatistics(d
                                                                                                            .getType()
                                                                                                            .longValue(), d.getDate(), d.getNumber()))
                                                                       .collect(Collectors.toList()));

        Map<String, List<DateStatistics>> result = new LinkedHashMap<>();
        // 用电
        result.put("electricList", WidgetUtil.findDateStatistics(rangeStatistics.getDates(), el));
        // 用气
        result.put("compressedAirData", WidgetUtil.findDateStatistics(rangeStatistics.getDates(), compress));
        // 用水
        result.put("waterData", WidgetUtil.findDateStatistics(rangeStatistics.getDates(), softening));
        // 空调热能
        //result.put("thermalList", WidgetUtil.findDateStatistics(rangeStatistics.getDates(), air));

        UnitOfStatistics unitOfStatistics = new UnitOfStatistics();
        unitOfStatistics.setMap(result);
        unitOfStatistics.setElectricity(WidgetUtil
                                                .findDateStatistics(rangeStatistics.getDates(), el)
                                                .stream()
                                                .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                                                .sum());
        unitOfStatistics.setWater(WidgetUtil
                                          .findDateStatistics(rangeStatistics.getDates(), softening)
                                          .stream()
                                          .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                                          .sum());
        unitOfStatistics.setGas(WidgetUtil
                                        .findDateStatistics(rangeStatistics.getDates(), compress)
                                        .stream()
                                        .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                                        .sum());
        return unitOfStatistics;
    }

    @Override
    public WorkShopUnitStatistics findWorkshopEnergyTce(Integer workshopId, String range, LocalDate begin, LocalDate end, Integer unit) {
        RangeStatistics rangeStatistics = WidgetUtil.findDateByRange(range, begin, end, "%Y-%m-%d", "'%Y-%m-%d'");

        //用电
        List<DateByStatistics> dateByStatistics = new ArrayList<>();
        //用水
        //自来水
        List<DateStatistics> daoTotalCostWater = new ArrayList<>();
        //冷却水
        List<DateStatistics> daoTotalCooling = new ArrayList<>();
        //用气
        List<DateStatistics> totalEnergy = overallEnergyDao.findConsumeWaterByUnit(rangeStatistics.getDatetime(), workshopId, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd());
        List<DateStatistics> daoTotalCoolingGas = totalEnergy
                .stream()
                .filter(d -> d.getCount() == 4L)
                .collect(Collectors.toList());
        List<DateStatistics> daoTotalVapour = totalEnergy
                .stream()
                .filter(d -> d.getCount() == 6L)
                .collect(Collectors.toList());

        // 默认单位：能耗
        if (unit == 0) {
            List<DateByStatistics> daoTotalCost = deviceEnergyMapper.findConsumeElectricity(rangeStatistics.getDatetime(), workshopId, null, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd());
            dateByStatistics = WidgetUtil.mergeByDateBy(daoTotalCost);
            // 自来水=(软化水)
            daoTotalCostWater = overallEnergyDao
                    .findConsumeWaterByUnit(rangeStatistics.getDatetime(), workshopId, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd())
                    .stream()
                    .filter(d -> d.getCount() == 2L)
                    .collect(Collectors.toList());
            // 冷却水能耗
            daoTotalCooling = overallEnergyDao
                    .findConsumeWaterByUnit(rangeStatistics.getDatetime(), workshopId, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd())
                    .stream()
                    .filter(d -> d.getCount() == 1L)
                    .collect(Collectors.toList());
        }
        // 能耗价格：万元
        if (unit == 1) {
            List<DateByStatistics> daoTotalCost = deviceEnergyMapper.findConsumeElectricityPrice(rangeStatistics.getDatetime(), workshopId, null, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd());
            dateByStatistics = WidgetUtil.mergeByDateBy(daoTotalCost);

            dateByStatistics.stream().forEach(d -> {
                d.setNumber(new BigDecimal(d.getNumber() / 10000).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
            });
            //dateByStatistics = WidgetUtil.setPriceByBigUnit(WidgetUtil.mergeByDateBy(WidgetUtil.computeByPrice(daoTotalCost, price)));

            // 自来水(软化水) * 单价
            daoTotalCostWater = overallEnergyDao.findConsumeWater(rangeStatistics.getDatetime(), workshopId, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd());

            // 电费 -> 1：设备类型为冷却水的
            List<DateByStatistics> daoTotalByCooling = deviceEnergyMapper.findConsumeElectricityPrice(rangeStatistics.getDatetime(), workshopId, null, null, 1, rangeStatistics.getBegin(), rangeStatistics.getEnd());
            // 得到总用电
            List<DateStatistics> electricity = WidgetUtil.mergeByElectricityPrice(daoTotalByCooling);
            // 冷却水能耗
            daoTotalCooling = overallEnergyDao
                    .findConsumeWaterByUnit(rangeStatistics.getDatetime(), workshopId, null, null, rangeStatistics.getBegin(), rangeStatistics.getEnd())
                    .stream()
                    .filter(d -> d.getCount() == 1L)
                    .collect(Collectors.toList());
            // 得到总能耗
            List<DateStatistics> cooling = WidgetUtil.mergeByEnergyPrice(daoTotalCooling);
            // 总冷却水设备电费/总冷却水(流量计m3)=冷却水单价x冷却水能耗m3=冷却水费用
            daoTotalCooling.stream().forEach(d -> {
                if (electricity.isEmpty()) {
                    electricity.add(new DateStatistics(0L, "", 0.00));
                }
                if (cooling.isEmpty() || cooling.get(0).getNumber() == 0.00) {
                    cooling.add(new DateStatistics(0L, "", 1.00));
                    cooling.get(0).setNumber(1.00);
                }
                Double unitPrice = electricity.stream().findFirst().get().getNumber() / cooling
                        .stream()
                        .findFirst()
                        .get()
                        .getNumber();
                d.setNumber(new BigDecimal(d.getNumber() * unitPrice / 10000)
                                    .setScale(4, BigDecimal.ROUND_HALF_UP)
                                    .doubleValue());
            });

            // 电费 -> 1：设备类型为压缩空气的
            List<DateByStatistics> daoTotalByCoolingGas = deviceEnergyMapper.findConsumeElectricityPrice(rangeStatistics.getDatetime(), workshopId, null, null, 4, rangeStatistics.getBegin(), rangeStatistics.getEnd());
            // 得到总用电
            List<DateStatistics> electricityGas = WidgetUtil.mergeByElectricityPrice(daoTotalByCoolingGas);
            // daoTotalCooling filter4=压缩空气能耗
            // 得到总能耗
            List<DateStatistics> coolingGas = WidgetUtil.mergeByEnergyPrice(daoTotalCoolingGas);
            // 总压缩空气设备电费/总压缩空气(流量计m3)=压缩空气单价x压缩空气能耗m3=压缩空气费用
            daoTotalCoolingGas.stream().forEach(d -> {
                if (electricityGas.isEmpty()) {
                    electricityGas.add(new DateStatistics(0L, "", 0.00));
                }
                if (coolingGas.isEmpty() || coolingGas.get(0).getNumber() == 0.00) {
                    coolingGas.add(new DateStatistics(0L, "", 1.00));
                    coolingGas.get(0).setNumber(1.00);
                }
                Double unitPrice = electricityGas.stream().findFirst().get().getNumber() / coolingGas
                        .stream()
                        .findFirst()
                        .get()
                        .getNumber();
                d.setNumber(new BigDecimal(d.getNumber() * unitPrice / 10000)
                                    .setScale(4, BigDecimal.ROUND_HALF_UP)
                                    .doubleValue());
            });
            // daoTotalVapour filter6=蒸汽能耗
            // 天然气费 天然气费(一个月)÷蒸汽用量(一个月)=单价x蒸汽能耗m3
            List<DateStatistics> natural = purchasingEnergyDao.findNaturalByDate(rangeStatistics.getDatetime(), rangeStatistics.getBegin(), rangeStatistics.getEnd());
            List<DateStatistics> TotalNatural = WidgetUtil.mergeByEnergyPrice(daoTotalVapour);
            daoTotalVapour.stream().forEach(d -> {
                if (natural.isEmpty()) {
                    natural.add(new DateStatistics(0L, "", 0.00));
                }
                if (TotalNatural.isEmpty() || TotalNatural.get(0).getNumber() == 0.00) {
                    TotalNatural.add(new DateStatistics(0L, "", 1.00));
                    TotalNatural.get(0).setNumber(1.00);
                }
                Double unitPrice = natural.stream().findFirst().get().getNumber() / TotalNatural
                        .stream()
                        .findFirst()
                        .get()
                        .getNumber();
                d.setNumber(new BigDecimal(d.getNumber() * unitPrice / 10000)
                                    .setScale(4, BigDecimal.ROUND_HALF_UP)
                                    .doubleValue());
            });
        }

        // 7为尖电[spikes]，8为峰电[peaks]，9为平电[parity]，10为谷电[lowEbb]
        Map<String, List<DateStatistics>> electricityResult = new LinkedHashMap<>();
        electricityResult.put("spikes", WidgetUtil.mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), dateByStatistics
                .stream()
                .filter(d -> d.getType() == 7)
                .collect(Collectors.toList())
                .stream()
                .map(d -> new DateStatistics(d.getType().longValue(), d.getDate(), d.getNumber()))
                .collect(Collectors.toList()))));
        electricityResult.put("peaks", WidgetUtil.mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), dateByStatistics
                .stream()
                .filter(d -> d.getType() == 8)
                .collect(Collectors.toList())
                .stream()
                .map(d -> new DateStatistics(d.getType().longValue(), d.getDate(), d.getNumber()))
                .collect(Collectors.toList()))));
        electricityResult.put("parity", WidgetUtil.mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), dateByStatistics
                .stream()
                .filter(d -> d.getType() == 9)
                .collect(Collectors.toList())
                .stream()
                .map(d -> new DateStatistics(d.getType().longValue(), d.getDate(), d.getNumber()))
                .collect(Collectors.toList()))));
        electricityResult.put("lowEbb", WidgetUtil.mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), dateByStatistics
                .stream()
                .filter(d -> d.getType() == 10)
                .collect(Collectors.toList())
                .stream()
                .map(d -> new DateStatistics(d.getType().longValue(), d.getDate(), d.getNumber()))
                .collect(Collectors.toList()))));

        // 冷却水[cooling]，自来水[tap]，软化水[softening]
        Map<String, List<DateStatistics>> waterResult = new LinkedHashMap<>();
        waterResult.put("cooling", WidgetUtil.mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), daoTotalCooling)));
        // result.put("tap", WidgetUtil.findDateStatistics(rangeStatistics.getDates(), daoTotalCost));
        waterResult.put("softening", WidgetUtil.mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), daoTotalCostWater)));

        // 压缩空气[compress]，蒸汽[vapour]
        Map<String, List<DateStatistics>> gasResult = new LinkedHashMap<>();
        gasResult.put("compress", WidgetUtil.mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), daoTotalCoolingGas)));
        gasResult.put("vapour", WidgetUtil.mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), daoTotalVapour)));

        Map<String, Map<String, List<DateStatistics>>> result = new LinkedHashMap<>();
        result.put("electricity", electricityResult);
        result.put("water", waterResult);
        result.put("gas", gasResult);

        WorkShopUnitStatistics workShopUnitStatistics = new WorkShopUnitStatistics();
        workShopUnitStatistics.setMap(result);
        workShopUnitStatistics.setElectricity(new BigDecimal(WidgetUtil
                                                                     .mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), dateByStatistics
                                                                             .stream()
                                                                             .filter(d -> d.getType() == 7)
                                                                             .collect(Collectors.toList())
                                                                             .stream()
                                                                             .map(d -> new DateStatistics(d
                                                                                                                  .getType()
                                                                                                                  .longValue(), d.getDate(), d.getNumber()))
                                                                             .collect(Collectors.toList())))
                                                                     .stream()
                                                                     .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                                                                     .sum() + WidgetUtil
                .mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), dateByStatistics
                        .stream()
                        .filter(d -> d.getType() == 8)
                        .collect(Collectors.toList())
                        .stream()
                        .map(d -> new DateStatistics(d.getType().longValue(), d.getDate(), d.getNumber()))
                        .collect(Collectors.toList())))
                .stream()
                .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                .sum() + WidgetUtil
                .mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), dateByStatistics
                        .stream()
                        .filter(d -> d.getType() == 9)
                        .collect(Collectors.toList())
                        .stream()
                        .map(d -> new DateStatistics(d.getType().longValue(), d.getDate(), d.getNumber()))
                        .collect(Collectors.toList())))
                .stream()
                .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                .sum() + WidgetUtil
                .mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), dateByStatistics
                        .stream()
                        .filter(d -> d.getType() == 10)
                        .collect(Collectors.toList())
                        .stream()
                        .map(d -> new DateStatistics(d.getType().longValue(), d.getDate(), d.getNumber()))
                        .collect(Collectors.toList())))
                .stream()
                .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                .sum()).setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());

        workShopUnitStatistics.setWater(WidgetUtil
                                                .mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), daoTotalCooling))
                                                .stream()
                                                .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                                                .sum() + WidgetUtil
                .mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), daoTotalCostWater))
                .stream()
                .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                .sum());

        workShopUnitStatistics.setGas(WidgetUtil
                                              .mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), daoTotalCoolingGas))
                                              .stream()
                                              .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                                              .sum() + WidgetUtil
                .mergeElementByNow(WidgetUtil.findDateStatistics(rangeStatistics.getDates(), daoTotalVapour))
                .stream()
                .mapToDouble(DateStatistics -> DateStatistics.getNumber())
                .sum());
        return workShopUnitStatistics;
    }

    @Override
    public RangeStatistics findDateByRange(String range, LocalDate begin, LocalDate end, String format, String datetime) {

        List<String> dates = new ArrayList();

        if (StrUtil.isEmpty(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            end = end.plusDays(1);
            for (LocalDate date = begin; date.isBefore(end); date = date.plusDays(1)) {
                dates.add(formatter.format(date));
            }
        }

        if (Day.equals(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            begin = begin.plusDays(-begin.getDayOfMonth() + 1);
            end = end.plusDays(-end.getDayOfMonth() + 1);
            end = end.plusMonths(1);
            for (LocalDate date = begin; date.isBefore(end); date = date.plusDays(1)) {
                dates.add(formatter.format(date));
            }
        } else if (HOUR.equals(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            end = end.plusDays(1);
            datetime = "'%H'";
            for (int hour = 0; hour <= 23; hour++) {
                if (hour < 10) {
                    dates.add(String.format("%02d", hour));
                } else {
                    dates.add(hour + "");
                }
            }
        } else if (WEEK.equals(range)) {
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(zone);
            begin = begin.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
            end = end.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
            end = end.plusDays(1);
            for (LocalDate date = begin; date.isBefore(end); date = date.plusDays(1)) {
                dates.add(formatter.format(date));
            }
        } else if (MONTH.equals(range)) {
            begin = begin.plusDays(-begin.getDayOfYear() + 1);
            end = begin.plusMonths(11);
            format = "%Y-%m";
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM").withZone(zone);
            end = end.plusMonths(1);
            for (LocalDate date = begin; date.isBefore(end); date = date.plusMonths(1)) {
                dates.add(formatter.format(date));
            }
            datetime = "'%Y-%m'";
        }
        return new RangeStatistics(dates, begin, end, format, datetime);
    }

    @Override
    public Integer setDayEnergyByHourEnergy() {
        Integer count = overallEnergyDao.setDayEnergyByHourEnergy();
        return count;
    }

    @Override
    public List<Building> findAllFloorByBuildingId(Integer buildId) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 管理员查看所有
        if (user.isAdmin()) {
            List<Building> buildings = buildingDao.findAllFloorByBuildingId(buildId);
            return buildings;
        }
        List<Building> buildings1 = buildingDao.findAllFloorByDeptId(buildId, SecurityUtils.getDeptId().intValue());
        return buildings1;
    }

    @Override
    public List<Workshop> findAllWorkshopByFloorId(Integer buildingId) {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 管理员查看所有
        if (user.isAdmin()) {
            List<Workshop> workshops = workshopDao.findAllWorkshopByFloorId(buildingId);
            // 过滤公共车间
            return workshops.stream().filter(w -> !w.getShopName().equals("公共")).collect(Collectors.toList());
        }
        // 根据部门找车间
        List<Workshop> workshops1 = workshopDao.findAllWorkshopByDeptId(SecurityUtils
                                                                                .getDeptId()
                                                                                .intValue(), buildingId);
        // 过滤公共车间
        return workshops1.stream().filter(w -> !w.getShopName().equals("公共")).collect(Collectors.toList());
    }


}
